import * as chokidar from 'chokidar';

import { Stats } from 'fs-extra';
import { WatcherEvent, AbstractWatcher } from './abstractWatcher';

type ChokidarPaths = string | string[];
type ChokidarOptions = chokidar.WatchOptions;
type ChokidarWatcher = chokidar.FSWatcher;

/**
 * Returns `true` to ignore the path.
 */
export type ChokidarIgnoredFunction = (path: string, stats: Stats) => boolean;

export class ChokidarFileWatcher extends AbstractWatcher {
  private static readonly _DEFAULT_OPTIONS: ChokidarOptions = {
    persistent: true,
    interval: 1000, // Increase the intervals when the chokidar fallbacks to polling,
    binaryInterval: 1000,
    disableGlobbing: true,
    ignoreInitial: true,
    ignorePermissionErrors: true
  };

  private _paths: ChokidarPaths;
  private _options: ChokidarOptions;
  private _watcher: ChokidarWatcher;

  constructor(paths: ChokidarPaths, options?: ChokidarOptions) {
    super();
    this._paths = paths;
    this._options = { ...ChokidarFileWatcher._DEFAULT_OPTIONS, ...options };
  }

  public start() {
    if (!this._watcher && this._paths) {
      this._watcher = chokidar.watch(this._paths, this._options);
      this._watcher.on('all', this._handleWatcherEvent);
    }
  }

  public stop() {
    if (this._watcher) {
      super.stop();
      this._watcher.close();
      this._watcher = undefined;
    }
  }

  private _handleWatcherEvent = (type: string, path: string) => {

    let eventType: WatcherEvent;
    switch (type) {
      case 'add':
        eventType = WatcherEvent.FileAdded;
        break;
      case 'addDir':
        eventType = WatcherEvent.DirectoryAdded;
        break;

      case 'change':
        eventType = WatcherEvent.FileChanged;
        break;

      case 'unlink':
        eventType = WatcherEvent.FileRemoved;
      case 'unlinkDir':
        eventType = WatcherEvent.DirectoryRemoved;
        break;

      default:
        return;
    }
    
    this.emit(eventType, path);
    this.emit(WatcherEvent.ALL, path);
  };
}

// function doProcess(filePath: string) {
//   console.log(filePath);
// }

// const watcher = new ChokidarFileWatcher('/Users/ellison/sim-agent/ellison/test');

// watcher.on(WatcherEvent.FileAdded, doProcess);
// watcher.on(WatcherEvent.FileChanged, doProcess);
// watcher.on(WatcherEvent.FileRemoved, doProcess);
// watcher.on(WatcherEvent.DirectoryRemoved, doProcess);

// watcher.start();